SViewBase for iOS 提供三维模型基本的浏览、模型属性操作、基本三维对象操作、动画播放、测量、批注等功能的实现接口,可实现基本的 三维模型展示功能,以便于用户个性化定制属于自己的产品。
集成之前需要熟悉集成环境、SViewBase for iOS的文件描述以及Xcode的工程配置,以便快速准确的集成相关功能界面。详细集成准备如下所示:
集成环境
SViewBase for iOS 开发库集成需要的环境:
  • 开发环境:Xcode 7.1以上版本
  • 系统环境: macOS 10.11以上版本
  • 运行环境: iOS 11.0以上64位真机
文件描述
SViewBase控件包包括:SViewBase.framework、SViewBase.bundle
  • SViewBase.framework:功能接口集成库。
  • SViewBase.bundle:资源包。
解压SViewBase控件包,得到SViewBase.framework和SViewBase.bundle两个文件,如下图所示:
Xcode配置
Xcode配置过程如下:
  • Xcode工程右侧相应目录下单击右键选择【Add Files to "工程名"】,选择iOSSViewBase,点击确定(或者直接拖拽控件包到工程相应目录下),成功添加后如下图所示:
  • Xcode工程配置中选择【Build Phases】,在【Link Binary With Libraries】中添加如下系统库:
    AVFoundation.framework
    CoreGraphics.framework
    QuartzCore.framework
    OpenGLES.framework
    Foundation.framework
    UIKit.framework
    libicucore.tbd
    libiconv.tbd
    libz.tbd
    成功配置后如下图所示:
  • Xcode工程配置中选择【Build Setting】,进行如下两项配置:
    • 【Enable Bitcode】配置为NO
    • 【Other Linker Flags】添加配置–ObjC
    • 【Compile Sources As】添加配置Objective C++
    成功配置后如下图所示:
集成SViewBase控件的过程中需要熟悉控件的文件内容和使用方法,下面我们做出了详细的引用说明和配置管理、控件对象初始化方法等相关说明。详细集成步骤请看如下描述 :
引用声明
使用控件,首先需要声明头文件
#import <SViewBase/SViewBase.h>
配置管理
控件对象初始化之前,需要对本地化资源路径、OpenGLES版本和License授权等信息进行初始配置 (此过程建议在程序启动后进行配置)
  • 申请授权文件sview.lic,并放在bundle中data文件夹下。(名称和位置要与规定一致)申请地址
  • OpenGLES版本号配置(默认为2.0)
  • [SParameters setGLESVersion:2.0];
  • 资源路径配置
  • NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    [SParameters setAppWorkPath:path];
注意事项:
  • gles版本设置后重新启动后有效,初次设置在对象初始化之前有效;
  • 路径下的文件具有读写的权限;
控件对象初始化
初始化对象,使用方法(指定视图大小):
- (id)initWithFrame:(CGRect)frame;
代码示例如下
// 初始化SViewBase对象
SViewBase *sviewBase = [[SViewBase alloc]initWithFrame:self.view.frame];
初始化完成后可根据需要添加到View视图中
需要用到多个SViewBase时,只需要重复创建添加多次即可。
注意事项:
  • 程序正常运行时,设置GLView开始界面刷新:
  • [sviewBase setGLViewRefresh:YES];
  • 程序退出或者进入后台运行时,停止GLView的定时刷新:
    [[sviewBase setGLViewRefresh:NO];
    以保证程序不会异常退出。
  • 由于渲染器占用初始化耗时较多,建议使用懒加载方式或者单例模式初始化(保证渲染器只初始化一次)
对象销毁
当对象需要销毁对象时:
//如果有已经打开的文件,关闭文件
[sviewBase close];

//将SViewBase从父视图上移除
[sviewBase removeFromSuperview];

//将SViewBase置为空,并将代理置为空
sviewBase.sviewBaseDelegate = nil;
sviewBase = nil;
智能测量
通过对拾取、预选及创建等相关接口的组合,实现快速测量尺寸,提高测量的易用性及用户体验;
  • 使用拾取器(或自定义拾取器)调用拾取接口传递坐标值,获取拾取到的特征点、线、面等对象;
  • 记录拾取到的对象并设置预选状态;
  • 使用类型及关系判断相关接口,确定对象之间的关系;
  • 调用对应的距离或角度测量接口创建测量对象;
预显
  • 根据传递的坐标值(x,y)获取拾取到的特征点、线、面等对象
  • 设置拾取到的对象的预选状态
        //获取拾取对象(getPickShapeX:(float)x y:(float)y), getPickShape:(CGPoint)point
        //1、根据拾取器坐标获取拾取到的对象集
        SShape *pickShape ;
        NSDictionary *dict = [self.sviewBase.measures.smartMeasureFactory getPickShapes:point];
        //2、根据拾取优先级获取拾取到的对象
        NSArray *pickTypes = weakSelf.sviewBase.measures.smartMeasureFactory.pickTypes;
        for (NSNumber *num in pickTypes) {
            pickShape = [dict valueForKey:num];
            if (pickShape != nil) {
                break;
            }
        }
        3、设置预选状态
        [[self.sviewBase.measures.smartMeasureFactory shape:pickShape preView:YES];

                                
关系判断
  • 线、面对象的类型判断详见 SViewBase for iOS API
  • 两个对象之间的关系判断(如两直线之间的平行、相交等关系)。
        //例 判断两直线是否平行
        1、记录拾取到的线对象;
        SLine *firstLineShape = getPickShape:point;

        SLine *secondLineShape = getPickShape:point;

        2、判断拾取对象关系
        //是否平行
        boolean isParallel = [self.sviewBase.measures.smartMeasureFactory shape:firstLineShape isParallel:secondLineShape];

                                
距离测量
  • 根据传递的坐标值(x,y)获取拾取到的特征点、线、面等对象
  • 记录并设置拾取到的对象的预选状态
  • 根据拾取到的对象类型执行距离测量
        //例 点线距离测量
        1、记录拾取到的点、线对象;
        SPoint *pntShape = getPickShape:point;

        SLine *lineShape = getPickShape:point;

        2、执行距离测量,如果满足是弧线,则进行点到弧线圆心的距离测量
        //判断是否是圆弧线
        boolean isCircleLine = [self.sviewBase.measures.smartMeasureFactory isCirCleLine:lineShape];
        SMeasure *measure;
        if(isCircleLine){
            //执行点到圆弧圆心的距离测量
            measure =[self.sviewBase.measures.smartMeasureFactory createDistanceMeasureWithPnt:pntShape circleLine:lineShape];
        }else{
            //执行点到圆弧最近距离测量
            measure = [self.sviewBase.measures.smartMeasureFactory createPntLineDistanceMeasure:pntShape second:lineShape];
        }
                                
角度测量
  • 根据传递的坐标值(x,y)获取拾取到的线、面对象
  • 记录并设置拾取到的对象的预选状态
  • 根据拾取到的对象类型执行角度测量
        //例 面面角度测量
        1、记录拾取对象;
        SFace *firstFaceShape = getPickShape:point;

        SFace *secondFaceShape = getPickShape:point;;

        2、判断是否是平面,只有平面可以进行角度测量
        boolean isPlaneFace1 = [self.sviewBase.measures.smartMeasureFactory isPlaneFace:firstFaceShape];
        boolean isPlaneFace2 = [self.sviewBase.measures.smartMeasureFactory isPlaneFace:secondFaceShape];
        SMeasure *measure;
        if(isPlaneFace1 && isPlaneFace2){
            //执行面面角度测量
            measure = [self.sviewBase.measures.smartMeasureFactory createFaceFaceDistanceMeasure:firstFaceShape second:secondFaceShape];
        }
                                
调用控件方法
以SViewBase for iOS API接口文档中打开本地文件接API接口文档中打开本地文件为例
- (BOOL) open:(NSString*)filePath asyn:(BOOL)asyn percent:(FileReadPercentBlock)percentBlock finish:(FinishOpenBlock)finishBlcok;
[sviewBase open:filePath asyn:YES percent:^(CGFloat percent) {
    
                                } finish:^(SVL_STATUS status) {
                                
                                }];
sviewBase为控件对象 open为控件提供的接口方法 filePath为打开模型文件路径 asyn是否为异步加载模型 percent加载进度回调 finish加载完成的回调
常见问题
  • 在sviewBase没有释放的情况下,App退出后台导致崩溃:
    • 由于openGL不能后台刷新,所以在程序进入后台之前,需要将sviewBase对象的刷新暂停,代码如下:
    • - (void)applicationWillResignActive:(UIApplication *)application {
            //设置SViewBase开始刷新
           [sviewBase setGLViewRefresh:NO];
      }
      同时,在程序重新进入前台时,需要设置sviewBase继续刷新,代码如下:
      - (void)applicationDidBecomeActive:(UIApplication *)application {
           //设置SViewBase开始刷新
           [sviewBase setGLViewRefresh:YES];
      }
  • SViewBase.framework文件中引用了JSONKit类,如果工程中也许使用JSONKit类,只保留头文件即可,把JSONKit.m删除;如果和其他类库出现JSONKit的调用冲突;出现类似这样的错误:
    duplicate symbol _OBJC_METACLASS_$_JKSerializer in:
        /Users/tony/Desktop/XXXProject/iOSSViewBase/SViewBase.framework(JSONKit.o)
        /Users/tony/Library/Developer/Xcode/DerivedData/XXXProject-boqkajmzatzxohbyrrhklfiuknic/Build/Products/Debug-iphoneos/libPods.a(JSONKit.o)
    ld: 24 duplicate symbols for architecture armv7
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    如果出现类似错误,解决方法如下:
    • 首先按照上述错误中提到的路径找到库文件:/Users/tony/Desktop/XXXProject/iOSSViewBase/SViewBase.framework,将它拷贝一份出来做进一步处理
    • 打开终端,并cd到文件夹下,使用lipo -info SViewBase.framework/SViewBase查看该文件下的架构信息, 留待后用
    • 使用命令lipo SViewBase.framework/SViewBase -thin armv7 -output SViewBase.framework/SViewBase.armv7 、lipo SViewBase.framework/SViewBase -thin arm64 -output SViewBase.framework/SViewBase.arm64,分离出其它的文件
    • 查看文件列表:ar -t SViewBase.framework/SViewbase.arm64、ar -t SViewBase.framework/SViewbase.armv7
    • 使用命令组合文件:lipo –create SViewBase.framework/SViewbase.arm64 SViewBase.framework/SViewbase.armv7 -output SViewBase.framework/SViewbase删除SViewbase.arm64、SViewbase.armv7文件
    • 将修改好的文件, 拖拽到原文件夹下,替换原文件即可